package routers

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-session/gin-session"
	"log"
	"strconv"
	"xuanshang/gotask/blocks"
)

// RespData 通用响应消息格式
type RespData struct {
	Code string      `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

// 自定义一套错误码
const (
	RESP_OK         = "0"
	RESP_PARAMERR   = "1"
	RESP_LOGINERR   = "2"
	RESP_BLOCKERR   = "3"
	RESP_UNKNOWNERR = "4"
	RESP_SESSIONERR = "5"
)

// 返回的错误信息记录 map
var respMap map[string]string = map[string]string{
	RESP_OK:         "正常",
	RESP_PARAMERR:   "参数异常",
	RESP_LOGINERR:   "登录失败",
	RESP_BLOCKERR:   "区块链操作失败",
	RESP_UNKNOWNERR: "未知异常",
	RESP_SESSIONERR: "session操作错误",
}

func getRespMsg(code string) string {
	return respMap[code]
}

func respJsonMsg(c *gin.Context, r *RespData) {
	r.Msg = getRespMsg(r.Code)
	c.JSON(200, r)
}

type UserInfo struct {
	UserName string `json:"username"`
	Password string `json:"password"`
}

// Register 注册功能函数
func Register(c *gin.Context) {
	// 3. 组织响应消息
	var resp RespData
	resp.Code = RESP_OK
	defer respJsonMsg(c, &resp)
	// 1. 解析请求消息
	var userInfo UserInfo
	if err := c.ShouldBindJSON(&userInfo); err != nil {
		resp.Code = RESP_PARAMERR
		log.Panic("failed to ShouldBindJSON", err)
		return
	}
	// 2. 业务规则处理
	if err := blocks.Register(userInfo.UserName, userInfo.Password); err != nil {
		resp.Code = RESP_BLOCKERR
		return
	}
}

// Login 登录请求
func Login(c *gin.Context) {
	var resp RespData
	resp.Code = RESP_OK
	defer respJsonMsg(c, &resp)
	// 解析请求消息
	var ui UserInfo
	if err := c.ShouldBindJSON(&ui); err != nil {
		resp.Code = RESP_PARAMERR
		log.Panic("failed to ShouldBindJSON", err)
		return
	}
	// 业务规则处理
	ok, err := blocks.Login(ui.UserName, ui.Password)
	if err != nil {
		resp.Code = RESP_BLOCKERR
		fmt.Println("failed to blocks Login", err)
		return
	}
	if !ok {
		fmt.Println("user not exists or passwd err")
		resp.Code = RESP_LOGINERR
		return
	}

	// 设置 session
	store := ginsession.FromContext(c)
	store.Set("username", ui.UserName)
	store.Set("password", ui.Password)
	if err = store.Save(); err != nil {
		fmt.Println("failed to set session", err)
		resp.Code = RESP_SESSIONERR
		return
	}
}

// Issue 任务发布
func Issue(c *gin.Context) {
	var resp RespData
	resp.Code = RESP_OK
	defer respJsonMsg(c, &resp)
	// 解析请求数据
	var taskInfo blocks.TaskMsg
	if err := c.ShouldBindJSON(&taskInfo); err != nil {
		fmt.Println("failed to ShouldBindJSON", err)
		resp.Code = RESP_PARAMERR
		return
	}
	// 读取 session
	store := ginsession.FromContext(c)
	username, ok := store.Get("username")
	if !ok {
		fmt.Println("failed to get session data")
		resp.Code = RESP_SESSIONERR
		return
	}
	passwd, b := store.Get("password")
	if !b {
		fmt.Println("failed to get session data")
		resp.Code = RESP_SESSIONERR
		return
	}
	// 业务处理，调用智能合约实现任务的发布
	if err := blocks.Issue(username.(string), passwd.(string), taskInfo.Desc, taskInfo.Bonus); err != nil {
		fmt.Println("failed to blocks Issue", err)
		resp.Code = RESP_BLOCKERR
		return
	}
}

// Update 任务修改
func Update(c *gin.Context) {
	var resp RespData
	resp.Code = RESP_OK
	defer respJsonMsg(c, &resp)
	// 解析请求数据
	var taskInfo blocks.TaskMsg
	if err := c.ShouldBindJSON(&taskInfo); err != nil {
		fmt.Println("failed to ShouldBindJSON", err)
		resp.Code = RESP_PARAMERR
		return
	}
	// 读取 session
	store := ginsession.FromContext(c)
	username, ok := store.Get("username")
	if !ok {
		fmt.Println("failed to get session data")
		resp.Code = RESP_SESSIONERR
		return
	}
	passwd, b := store.Get("password")
	if !b {
		fmt.Println("failed to get session data")
		resp.Code = RESP_SESSIONERR
		return
	}
	// 业务处理，调用智能合约实现任务修改
	taskId, err := strconv.Atoi(taskInfo.TaskID)
	if err != nil {
		fmt.Println("failed to strconv Atoi", err)
		resp.Code = RESP_UNKNOWNERR
		return
	}
	if err := blocks.Update(username.(string), passwd.(string), taskInfo.Comment, taskInfo.TaskStatus, int64(taskId)); err != nil {
		fmt.Println("failed to blocks Update", err)
		resp.Code = RESP_BLOCKERR
		return
	}
}

// TaskList 任务列表查询
func TaskList(c *gin.Context) {
	var resp RespData
	resp.Code = RESP_OK
	defer respJsonMsg(c, &resp)
	// 请求数据解析
	page := c.Query("page")
	ipage, err := strconv.Atoi(page)
	if err != nil {
		fmt.Println("failed to strconv Atoi", err)
		resp.Code = RESP_UNKNOWNERR
		return
	}
	// 业务规则处理，调用智能合约实现
	tasks, err := blocks.TaskList()
	if err != nil {
		fmt.Println("failed to blocks TaskList", err)
		resp.Code = RESP_BLOCKERR
		return
	}
	// 重新设置响应消息中的任务列表数据, 对列表实现了分页
	begin := (ipage - 1) * 10
	end := ipage * 10
	if end > len(tasks) {
		end = len(tasks)
	}
	data := struct {
		Total int         `json:"total"`
		Data  interface{} `json:"data"`
	}{Total: len(tasks), Data: tasks[begin:end]}
	resp.Data = data
}
